package org.seedframework.sharding.mybatis;

import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.seedframework.sharding.annotations.DoubleWrite;
import org.seedframework.sharding.annotations.Scatter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;

import java.lang.reflect.Method;


@Slf4j
public class MapperFactoryDoubleWriteBeanAware implements BeanPostProcessor, ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        try {
            if (!(bean instanceof MapperFactoryBean)) {
                return bean;
            }
            MapperFactoryBean mapperFactoryBean = (MapperFactoryBean) bean;
            Scatter scatterAnn = (Scatter) mapperFactoryBean.getObjectType().getAnnotation(Scatter.class);
            DoubleWrite annotation = (DoubleWrite) mapperFactoryBean.getObjectType().getAnnotation(DoubleWrite.class);
            if (annotation != null) {
                Assert.isNull(scatterAnn,"@DoubleWrite annotation can't use both with annotation @Scatter.");
                Class mapperInterface = mapperFactoryBean.getMapperInterface();
                Method[] methods = mapperInterface.getMethods();
                String className = mapperInterface.getName();
                for (Method method : methods) {
                    String fullMethodPath = className + "." + method.getName();
                    MultiWriteSupport.addMethodPath(fullMethodPath,annotation.group());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;

    }

}
